//------------------------------------------------------------------------------
// <copyright file="OptionsWindowViewModel.cs" company="Damian Antonowicz">
//       copyright © 2010 Damian Antonowicz
// </copyright>
// <author>Damian Antonowicz</author>
// <email>poczta@damianantonowicz.pl</email>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.ComponentModel;
using DAnton.Utilities.Helpers;
using DAnton.Utilities.Extensions;
using System.Diagnostics;
using System.Reflection;
using DotBeer.UI.WPFClient.Commands;
using DotBeer.Business.Components.Exceptions;

namespace DotBeer.UI.WPFClient.ViewModels
{
    public class OptionsWindowViewModel : ViewModelBase
    {
        #region private members

        DelegateCommand saveCommand,
                        cancelCommand;

        IList<TreeViewItem> optionsList = new List<TreeViewItem>();
        IList<IOptionsControl> optionControls = new List<IOptionsControl>();
        TreeViewItem selectedOption;
        FrameworkElement currentOptionControl;

        IOptionsControl heroesCollectionControl,
                        tavernsCollectionControl,
                        itemsCollectionControl,
                        copyItemBuildControl,
                        copySkillBuildControl,
                        updateOptionsControl,
                        restoreDefaultSettingsControl,
                        keyBindingsControl;

        bool changesCancelled = false;

        #endregion

        #region properties

        public event EventHandler CloseViewRequested;

        public IList<TreeViewItem> Options
        {
            get { return this.optionsList; }
        }

        public TreeViewItem SelectedOption
        {
            get { return this.selectedOption; }
            set
            {
                this.selectedOption = value;
                this.ChangeCurrentOptionControl();
            }
        }

        public FrameworkElement CurrentOptionControl
        {
            get { return this.currentOptionControl; }
        }

        #region commands

        public DelegateCommand SaveCommand
        {
            get
            {
                if (this.saveCommand == null)
                    this.saveCommand = new DelegateCommand(this.Save);

                return this.saveCommand;
            }
        }

        public DelegateCommand CancelCommand
        {
            get
            {
                if (this.cancelCommand == null)
                    this.cancelCommand = new DelegateCommand(this.Cancel);

                return this.cancelCommand;
            }
        }

        #endregion

        #endregion

        #region constructors

        public OptionsWindowViewModel()
        {
            this.AddOptions();
        }

        #endregion

        #region public methods

        public void HandleViewClosing()
        {
            if (!this.changesCancelled)
                this.Cancel();
        }

        #endregion

        #region private methods

        private void AddOptions()
        {
            TreeViewItem collectionsItem = new TreeViewItem()
            {
                Header = "Collections",
                IsExpanded = true
            };
            TreeViewItem heroesItem = new TreeViewItem() { Header = "Heroes" };
            TreeViewItem itemsItem = new TreeViewItem() { Header = "Items" };
            TreeViewItem tavernsItem = new TreeViewItem() { Header = "Taverns" };
            collectionsItem.Items.Add(heroesItem);
            collectionsItem.Items.Add(itemsItem);
            collectionsItem.Items.Add(tavernsItem);

            TreeViewItem copyBuildItem = new TreeViewItem()
            {
                Header = "Copy Build",
                IsExpanded = true
            };
            TreeViewItem itemBuildItem = new TreeViewItem() { Header = "Item Build" };
            TreeViewItem skillBuildItem = new TreeViewItem() { Header = "Skill Build" };
            copyBuildItem.Items.Add(itemBuildItem);
            copyBuildItem.Items.Add(skillBuildItem);

            TreeViewItem updatesItem = new TreeViewItem() { Header = "Updates" };
            TreeViewItem restoreItem = new TreeViewItem() { Header = "Restore settings" };
            TreeViewItem keyItem = new TreeViewItem() { Header = "Key bindings" };

            this.optionsList.Add(collectionsItem);
            this.optionsList.Add(copyBuildItem);
            this.optionsList.Add(updatesItem);
            this.optionsList.Add(restoreItem);
            this.optionsList.Add(keyItem);
        }

        private void ChangeCurrentOptionControl()
        {
            switch (this.selectedOption.Header.ToString().Trim())
            {
                case "Heroes":
                    this.AddOptionControl(ref this.heroesCollectionControl, typeof(HeroesCollectionControl));
                    break;
                case "Taverns":
                    this.AddOptionControl(ref this.tavernsCollectionControl, typeof(TavernsCollectionControl));
                    break;
                case "Items":
                    this.AddOptionControl(ref this.itemsCollectionControl, typeof(ItemsCollectionControl));
                    break;
                case "Item Build":
                    this.AddOptionControl(ref this.copyItemBuildControl, typeof(CopyItemBuildControl));
                    break;
                case "Skill Build":
                    this.AddOptionControl(ref this.copySkillBuildControl, typeof(CopySkillBuildControl));
                    break;
                case "Updates":
                    this.AddOptionControl(ref this.updateOptionsControl, typeof(UpdateOptionsControl));
                    break;
                case "Restore settings":
                    this.AddOptionControl(ref this.restoreDefaultSettingsControl, typeof(RestoreDefaultSettingsControl));
                    break;
                case "Key bindings":
                    this.AddOptionControl(ref this.keyBindingsControl, typeof(KeyBindingsControl));
                    break;
            }
        }

        private void AddOptionControl(ref IOptionsControl control, Type controlType)
        {
            if (control == null)
            {
                ConstructorInfo ci = controlType.GetConstructor(new Type[] { });
                control = ci.Invoke(null) as IOptionsControl;
                this.optionControls.Add(control);
            }

            this.currentOptionControl = (FrameworkElement)control;
            this.OnPropertyChanged("CurrentOptionControl");
        }

        private void Save()
        {
            bool result = true;

            foreach (IOptionsControl control in this.optionControls)
            {
                try
                {
                    if (!control.Save())
                    {
                        result = false;
                        break;
                    }
                }
                catch (Exception ex)
                {
                    HandleExceptions.UIPolicy(ex);
                }
            }

            if (result)
                CustomMessageBox.Show("Saved successful.", "Information");
            else
                CustomMessageBox.Show("Saved unsuccessful.", "Error");
        }

        private void Cancel()
        {
            foreach (IOptionsControl cont in this.optionControls)
            {
                try
                {
                    cont.Cancel();
                }
                catch (Exception ex)
                {
                    HandleExceptions.UIPolicy(ex);
                }
            }

            this.changesCancelled = true;
            this.OnViewCloseRequested();
        }

        private void OnViewCloseRequested()
        {
            if (this.CloseViewRequested != null)
                this.CloseViewRequested(this, EventArgs.Empty);
        }

        #endregion
    }
}
